#include "common.h"

#define BUFFER_DEFAULT_SIZE 1024

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL INF // 将日志等级设置为INF

// 使用宏函数用\是为了将\r转义,因为宏只允许一行代码
// format: 声明类型
// ...: (参数)不定参的使用
#define LOG(level, format, ...) do{\
        if(level < LOG_LEVEL) break;\
        time_t t = time(NULL);\
        struct tm* lmt = localtime(&t);\
        char tmp[32];\
        strftime(tmp, 31, "%H:%M:%S", lmt);\
        /* ##_VA_ARGS__是解决空参数下的场景 */ \
        fprintf(stdout, "[%s %s:%d] " format "\n", tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
    }while(0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)


using std::endl;
using std::cout;
class Buffer
{
public:
    std::vector<char> _buffer;
    uint64_t _reader_idx;
    uint64_t _writer_idx;
public:
    Buffer():
    _reader_idx(0),
    _writer_idx(0),
    _buffer(BUFFER_DEFAULT_SIZE)
    {}

    char* Begin()
    {return &*_buffer.begin();}
    const char* Begin()const
    {return &*_buffer.begin();}

    // 获取当前读取起始地址
    char* GetReadaddress()
    {return Begin() + _reader_idx;} // 迭代器的*解引用是获取迭代器里某一成员指向的内容,再对这个内容进行&取地址操作
    const char* GetReadaddress()const
    {return Begin() + _reader_idx;}

    // 获取当前写入起始地址
    char* GetWriteaddress()
    {return Begin() + _writer_idx;}
    const char* GetWriteaddress()const
    {return Begin() + _writer_idx;}

    // 获取前沿剩余空间
    uint64_t HeadRemaining()
    {return _reader_idx;}

    // 获取后沿剩余空间
    uint64_t TailRemaining()
    {return _buffer.size() - _writer_idx;}

    // 将读偏移向后移动
    void MoveReadOffset(uint64_t len)
    {
        assert(len <= ReadableSpace()); // 读偏移最大不能超过写偏移
        _reader_idx += len;
    }

    // 将写偏移向后移动
    void MoveWriteOffset(uint64_t len)
    {
        assert(len <= TailRemaining());
        _writer_idx += len;
    }

    // 获取可读数据大小
    uint64_t ReadableSpace()
    {return _writer_idx - _reader_idx;}
    const uint64_t ReadableSpace()const
    {return _writer_idx - _reader_idx;}

    // 确保剩余空间可被写入
    void EnsureWritableSpace(uint64_t len)
    {
        if(len <= TailRemaining())
        {return;}
        if(len <= TailRemaining() + HeadRemaining())
        {
            // 保存目前的数据大小
            uint64_t datasz = ReadableSpace();
            std::copy(GetReadaddress(), GetWriteaddress(), Begin());
            _reader_idx = 0;
            _writer_idx = datasz;
        }
        else
        {
            _buffer.resize(_buffer.size() + len);
        }
    }
    
    
    // 写入数据
    void Write(const void* data, uint64_t len)
    {
        // 1.先确保空间可写入 2.写入数据(copy)
        EnsureWritableSpace(len);
        const char* d = (const char*) data; // 强转,下面的copy要求三个参数的类型相同
        std::copy(d, d + len, GetWriteaddress());
    }

    void WriteAndPush(const void* data, uint64_t len)
    {
        Write(data, len);
        MoveWriteOffset(len);
    }

    // 以传入string类型的方式写入
    void WriteString(const std::string& str)
    {
        Write(str.c_str(), str.size());
    }

    void WriteStringAndPush(const std::string& str)
    {
        WriteString(str);
        // cout << "****" << str << endl;
        MoveWriteOffset(str.size());
    }

    // 以传入Buffer类型的方式写入
    void WriteBuffer(Buffer& buf)
    {
        // 传入可读数据的地址         传入可读数据的大小
        Write(buf.GetReadaddress(), buf.ReadableSpace());
    }
    void WriteBufferAndPush(Buffer& buf)
    {
        WriteBuffer(buf);
        MoveWriteOffset(buf.ReadableSpace());
    }

    // 读取数据
    void Read(void* buffer, uint64_t len)
    {
        // std::cout << "ReadableSpace is :" << ReadableSpace() << "\n";
        assert(len <= ReadableSpace());
        // std::cout << "Read---对以写入的数据读取: " << GetReadaddress() << "\n";
        std::copy(GetReadaddress(), GetReadaddress() + len, (char*)buffer);
        // std::cout << "Read---对copy后的缓冲区读取: " << (char*)buffer << "\n";
    }
    void ReadAndPop(void* buffer, uint64_t len)
    {
        Read(buffer, len);
        MoveReadOffset(len);
    }
    std::string ReadString(uint64_t len)
    {
        std::string str;
        str.resize(len);
        // 传入的是string类对象里的第一个字符的地址
        Read(&str[0], len);
        // cout << "ReadString--str: " << str << endl;
        return str;
    }
    std::string ReadStringAndPop(uint64_t len)
    {
        assert(len <= ReadableSpace());
        std::string str = ReadString(len);
        // cout << "str: " << str << endl;
        MoveReadOffset(len);
        // cout << "Read_idx: " << _reader_idx << endl;
        return str;
    }

    char* GetCRLF()
    {
        // memchr函数,失败返回空
        return (char*)memchr(GetReadaddress(), '\n', ReadableSpace());
    }

    // 获取换行符前面的字符(包括换行符本身)
    std::string GetLine()
    {
        char* pos = GetCRLF();
        if(pos == nullptr)
            return "";
        return ReadString(pos - GetReadaddress() + 1);
    }

    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        MoveReadOffset(str.size());
        return str;
    }

    // 清空缓冲区
    void Clear()
    {
        _writer_idx = 0;
        _reader_idx = 0;
    }
};

#define MAX_LISTEN 1024
class Socket
{
private:
    int _sockfd;
public:
    Socket(){_sockfd = -1;}
    Socket(int fd):_sockfd(fd){}
    ~Socket(){
        Close();
    }
    int GetFd(){
        return _sockfd;
    }
    // 创建套接字
    bool Create()
    {
        int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(fd < 0)
            return false;
        _sockfd = fd;
        return true;
    }
    // 绑定地址信息
    bool Bind(const std::string& ip, uint16_t port)
    {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        memset(&addr, 0, len);
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        int n = bind(_sockfd, (struct sockaddr*)&addr, len);
        if(n < 0){
            ERR_LOG("BIND failed!");
            return false;
        }
        return true;
    }
    // 开始监听
    bool Listen(int backlog = MAX_LISTEN)
    {
        int ret = listen(_sockfd, MAX_LISTEN);
        if(ret < 0){
            ERR_LOG("Listen Failed!");
            return false;
        }
        return true;
    }
    // 向服务器发起连接
    bool Connect(const std::string& ip, uint16_t port)
    {
        struct sockaddr_in addr;
        socklen_t len = sizeof(struct sockaddr_in);
        memset(&addr, 0, len);
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        int n = connect(_sockfd, (struct sockaddr*)&addr, len);
        if(n < 0){
            ERR_LOG("Connect Server failed!");
            return false;
        }
        return true;        
    }
    // 获取新连接
    int Accept()
    {
        int fd = accept(_sockfd, NULL, NULL);
        if(fd < 0){
            ERR_LOG("Accpet Failed!");
            return -1;
        }
        return fd;
    }
    // 接收数据
    ssize_t/*有符号的size_t*/Recv(void* buf, size_t len, int flag = 0) // 默认使用非阻塞的方式
    {
        ssize_t ret = recv(_sockfd, buf, len, flag);
        if(ret <= 0)
        {
            // EAGAIN 当前sockfd的接收缓冲区没有数据了,非阻塞下才会有这错误
            // EINTR 当前sockfd的阻塞等待,被信号给打断了
            if(errno == EAGAIN || errno == EINTR){
                DBG_LOG("Signal or timeout");
                return 0;
            }
            ERR_LOG("Recv Failed!");
            return -1;
        }
        return ret;
    }
    // 以非阻塞的方式接收数据
    ssize_t RecvNonBlock(void* buf, size_t len)
    {
        return Recv(buf, len, MSG_DONTWAIT);
    }

    // 发送数据
    ssize_t Send(void* buf, size_t len, int flag = 0)
    {
        ssize_t ret = send(_sockfd, buf, len, flag);
        if(ret < 0){
            ERR_LOG("Send Failed!");
            return -1;
        }
        // 有可能会出现数据没有发送完的情况
        return ret; // 实际发送的数据长度
    }
    // 以非阻塞的方式发送数据
    ssize_t NonBlockSend(void* buf, size_t len)
    {
        return Send(buf, len, MSG_DONTWAIT);
    }
    // 关闭套接字
    void Close()
    {
        if(_sockfd != -1){
            close(_sockfd);
            _sockfd = -1;
        }
    }
    // 创建服务端连接
    bool CreateServer(uint16_t port, const std::string& ip = "0.0.0.0", bool block_flag = false) // 默认是阻塞状态
    {
        // 1.创建套接字 2.绑定地址 3.开始监听 4.设置套接字阻塞属性 5.开启地址端口重用
        if(Create() == false) {
            DBG_LOG("Create Falied!");
            return false;
        }
        // INF_LOG("_sockfd: %d", _sockfd);
        if(block_flag) NonBlock(); 
        if(Bind(ip, port) == false) return false;
        if(Listen() == false) return false;
        ReuseAddress();
        return true;
    }

    // 创建客户端连接
    bool CreateClient(uint16_t port, const std::string& ip)
    {
        // 1.创建套接字 2.连接服务端
        if(Create() == false) return false;
        DBG_LOG("%d", _sockfd);
        if(Connect(ip, port) == false) return false;
        return true;
    }

    // 设置套接字选项--取消timewait,开启地址端口重用
    void ReuseAddress()
    {
        int val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(val));
        val = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&val, sizeof(val));
    }

    //设置套接字阻塞属性--设置为非阻塞
    void NonBlock()
    {
        int state = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, state|O_NONBLOCK);
    }
};

//对于一个描述符的监控和事件管理
class Poller;
class Channel
{
private:
    int _fd;
    Poller* _poller;
    uint32_t _events; // 当前需要监控的事件
    uint32_t _revents;// 当前连接触发的事件
    using EventCallback = std::function<void()>;
    EventCallback _read_callback;   //可读事件被触发的回调函数
    EventCallback _write_callback;  //可写事件被触发的回回调函数
    EventCallback _error_callback;  //错误事件被触发的回回调函数
    EventCallback _close_callback;  //连接断开事件被触发的回回调函数
    EventCallback _event_callback;  //任意事件被触发的回回调函数
public:
    Channel(Poller* poller, int fd)
    :_fd(fd),
     _events(0),
     _revents(0),
     _poller(poller)
    {}
    int Fd() {return _fd;}
    void SetREvents(uint32_t events){_revents = events;}//设置实际就绪的事件
    uint32_t Events(){return _events;}//获取想要监控的事件
    void setReadCallback(const EventCallback& cb){_read_callback = cb;};
    void setWriteCallback(const EventCallback& cb){_write_callback = cb;};
    void setErrorCallback(const EventCallback& cb){_error_callback = cb;};
    void setCloseCallback(const EventCallback& cb){_close_callback = cb;};
    void setEventCallback(const EventCallback& cb){_event_callback = cb;};
    //当前是否监控可读
    bool ReadAble()
    {
        return (_events & EPOLLIN);
    }
    //当前是否监控可写
    bool WriteAble()
    {
        return (_events & EPOLLOUT);
    }
    //启动读事件监控
    void EnableRead()
    {
        (_events |= EPOLLIN);
        Update();
    }
    //启动写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    //关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN; //之后会修改到EventLoop的事件监控中 0010 -> 1101
        Update();
    }
    //关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT; //之后会修改到EventLoop的事件监控中 0010 -> 1101
        Update();
    }
    //关闭所有监控事件
    void DisablAll()
    {
        _events = 0;
        Update();
    }

    //移除监控(从红黑树中移除)
    void Remove();
    void Update();
    
    //事件处理,一但连接触发了连接,就调用这个函数,自己触发了什么事件如何处理由自己决定
    void HandlerEvent()
    {
        if((_events & EPOLLIN) || (_events & EPOLLRDHUP/*对方关闭的连接*/) || \
        (_revents & EPOLLPRI) /*优先数据*/)
        {
            //不管任何事件，都调用的回调函数
            if(_event_callback) _event_callback();
            if(_read_callback) _read_callback();
        }
        //有可能会释放连接的，一次只处理一个
        if(_revents & EPOLLOUT)
        {
            if(_event_callback) _event_callback();
            if(_write_callback) _write_callback();
        }
        else if(_revents & EPOLLERR)
        {
            if(_event_callback) _event_callback();
            //要在执行错误回调前，调用任意回调(错误回调会断开连接)
            if(_error_callback) _error_callback();
        }
        else if(_revents & EPOLLHUP)
        {
            if(_event_callback) _event_callback();
            if(_close_callback) _close_callback();
        }
    }
};

#define MAX_EPOLLEVENTS 1024
class Poller{
    private:
        int _epfd;
        struct epoll_event _evs[MAX_EPOLLEVENTS];
        std::unordered_map<int, Channel*> _channels;

    private:
        //对epoll的直接操作
        void Update(Channel* channel, int op/*op是实际要执行的命令*/)
        {
            // int epoll_ctl(int epfd, int op, int fd, struct epoll_event* ev);
            int fd = channel->Fd();
            struct epoll_event ev;
            ev.data.fd = fd;
            ev.events = channel->Events();
            int ret = epoll_ctl(_epfd, op, fd, &ev);
            if(ret < 0)
            {
                ERR_LOG("EPOLLCTL FAILED!");
                abort();//退出程序
            }
            return;
        }
        //判断一个Channel是否已经添加了事件监控(是否被哈希表管理起来)
        bool HasChannel(Channel* channel)
        {
            auto it = _channels.find(channel->Fd());
            if(it == _channels.end())
            {
                return false;
            }
            return true;
        }
    public:
        Poller()
        {
            _epfd = epoll_create(MAX_EPOLLEVENTS);
            if(_epfd < 0)
            {
                ERR_LOG("EPOLL CREATE FAILED!!");
                abort();//退出程序
            }
        }
        
        //添加或修改监控事件
        void UpdateEvent(Channel* channel)
        {
            bool ret = HasChannel(channel);
            if(ret == false)
            {
                //不存在则添加
                _channels.insert(std::make_pair(channel->Fd(), channel));
                return Update(channel, EPOLL_CTL_ADD);
            }
            //存在则更新
            return Update(channel, EPOLL_CTL_MOD);
        }

        //移除监控
        void RemoveEvent(Channel* channel)
        {
            Update(channel, EPOLL_CTL_DEL);
            auto it = _channels.find(channel->Fd());
            if(it != _channels.end())
            {
                //找到了
                _channels.erase(it);
            }
            Update(channel, EPOLL_CTL_DEL);
        }

        //开始监控，返回活跃连接
        void Poll(std::vector<Channel*>* active)
        {
            //int epoll_wait(int epfd, struct epoll_event* evs, int maxevents, int timeout)
            //返回的是有活跃事件的监控描述符  
            int nfds = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);//阻塞监控,没有描述符就绪就一直监控
            if(nfds < 0)
            {
                if(errno = EINTR)//阻塞被信号打断了
                {
                    return;
                }
                ERR_LOG("EPOLL WAIT ERROR:%s\n", strerror(errno));
                abort();//退出程序
            }
            for(int i = 0; i < nfds; i++)
            {
                auto it = _channels.find(_evs[i].data.fd);
                assert(it != _channels.end());
                it->second->SetREvents(_evs[i].events);//设置实际就绪的事件
                active->push_back(it->second);
            }
            return;
        }
};

void Channel::Remove()
{
    return _poller->RemoveEvent(this);
}
void Channel::Update()
{
    return _poller->UpdateEvent(this);
}